package com.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.common.PageMessage;
import com.demo.core.constants.HttpStatus;
import com.demo.core.exception.BusinessException;
import com.demo.core.exception.ParameterException;
import com.demo.dao.RegistrationInformationDao;
import com.demo.dao.TeamCompositionDao;
import com.demo.dao.TeamProfileDao;
import com.demo.dao.UserDao;
import com.demo.domain.RegistrationInformation;
import com.demo.domain.TeamComposition;
import com.demo.domain.TeamProfile;
import com.demo.domain.User;
import com.demo.domain.ro.AddRegInfoRequest;
import com.demo.domain.vo.RegistrationDisplayListView;
import com.demo.service.MessageService;
import com.demo.service.RegistrationInformationService;
import com.demo.service.TeamCompositionService;
import com.demo.utils.AuthorityUtils;
import com.demo.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class RegistrationInformationServiceImpl extends ServiceImpl<RegistrationInformationDao, RegistrationInformation> implements RegistrationInformationService {
    @Autowired
    RegistrationInformationDao registrationInformationDao;

    @Autowired
    TeamProfileDao teamProfileDao;

    @Autowired
    TeamCompositionDao teamCompositionDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private AuthorityUtils authorityUtils;

    @Autowired
    private TeamCompositionService teamCompositionService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private WebSocketServer webSocketServer;

    /*CRUD*/
    @Override
    public RegistrationInformation getByRiId(Long riId) throws ParameterException{
        if(riId == null){
            throw new ParameterException("null");
        }
        RegistrationInformation registrationInformation = registrationInformationDao.selectById(riId);
        if(registrationInformation.getRiDelFlag() == 1){
            return null;
        }
        return registrationInformation;
    }

    @Override
    public Integer insertRegistrationInformation(RegistrationInformation registrationInformation) throws ParameterException {
        int row = 0;
        if(registrationInformation.getRiUid()!=null && registrationInformation.getRiRealname()!=null && registrationInformation.getRiUnickname()!=null && registrationInformation.getRiContact()!= null && registrationInformation.getRiIntro()!=null && registrationInformation.getRiTeamId()!=null){
            row = registrationInformationDao.insert(registrationInformation);
        }else{
            return null;
        }
        return row;
    }

    @Override
    public Integer updateRegistrationInformation(RegistrationInformation registrationInformation) {
        int row = 0;
        if(registrationInformation.getRiId()!=null && registrationInformation.getRiUid()!=null && registrationInformation.getRiRealname()!=null && registrationInformation.getRiUnickname()!=null && registrationInformation.getRiContact()!= null && registrationInformation.getRiIntro()!=null && registrationInformation.getRiTeamId()!=null){
            row = registrationInformationDao.updateById(registrationInformation);
        }else{
            return null;
        }
        return row;
    }

    @Override
    public Integer deleteRegistrationInformationById(RegistrationInformation registrationInformation) throws ParameterException {
        int row = 0;
        if(registrationInformation.getRiId()!=null){
            row = registrationInformationDao.deleteRegistrationInformationById(registrationInformation);
        }

        return row;
    }

    @Override
    public List<RegistrationInformation> selectRegistrationInformationList(RegistrationInformation registrationInformation) throws ParameterException {
        List<RegistrationInformation> registrationInformationList = new ArrayList<>();
        if (registrationInformation.getRiUid()!=null || registrationInformation.getRiUnickname()!=null || registrationInformation.getRiRealname()!=null || registrationInformation.getRiContact()!= null ||  registrationInformation.getRiReviewStatus()!=null || registrationInformation.getRiTeamId()!=null) {
            registrationInformationList=registrationInformationDao.selectRegistrationInformationList(registrationInformation.getRiUid(),
                    registrationInformation.getRiUnickname(),registrationInformation.getRiRealname(),
                    registrationInformation.getRiContact(),registrationInformation.getRiReviewStatus(),
                    registrationInformation.getRiTeamId());
        }
        return registrationInformationList;
    }

    @Override
    public List<RegistrationInformation> listAllRegistrationInformation(){
        List<RegistrationInformation> registrationInformationList = registrationInformationDao.listAllRegistrationInformation();
        return registrationInformationList;
    }


    /**
     * 得到某个申请的详细信息
     *
     * @param riId
     * @param uid
     * @return
     * @throws Exception
     * @throws ParameterException
     */
    @Override
    public RegistrationInformation getOneRegistration(Long riId, Long uid) throws Exception, ParameterException {
        if (riId == null || riId < 0l) {
            throw new ParameterException("riId为空或值非法");
        }
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空或值非法");
        }
        //得到当前申请信息
        RegistrationInformation registrationInformation = registrationInformationDao.selectById(riId);
        if (registrationInformation != null) {
            //检查该队伍的当前状态（是否alive）
            TeamProfile teamProfile = teamProfileDao.selectById(registrationInformation.getRiTeamId());
            if (teamProfile != null && teamProfile.getTpAlive() == 1) {
                //检查申请人与uid是否匹配
                return registrationInformation.getRiUid().equals(uid) ?
                        registrationInformation : null;
            }
        }
        return null;
    }

    /**
     * 获取某人发出的搜索申请（队伍alive=0不展示）
     *
     * @param current
     * @param size
     * @param uid
     * @return
     * @throws Exception
     * @throws ParameterException
     */
    @Override
    public Page<RegistrationDisplayListView> getDisplayRegistrations(int current, int size, Long uid) throws Exception, ParameterException {
        if (current < 0 || size < 0) {
            throw new ParameterException("分页参数无效");
        }
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空或值非法");
        }
        List<Map<String, Object>> list = registrationInformationDao.selectRegistrationsToDisplayByUid(uid);
        if (list != null && list.size() > 0) {
            List<RegistrationDisplayListView> viewList = new ArrayList<>();
            list.stream().forEach(stringObjectMap -> {
                RegistrationDisplayListView view = new RegistrationDisplayListView();
                view.setRegistrationId(stringObjectMap.get("ri_id") != null ? Long.parseLong(stringObjectMap.get("ri_id") + "") : 0l);
                view.setUid(uid);
                view.setTeamId(stringObjectMap.get("ri_team_id") != null ? Long.parseLong(stringObjectMap.get("ri_team_id") + "") : 0l);
                view.setTeamName(stringObjectMap.get("tp_team_name") != null ? (String) stringObjectMap.get("tp_team_name") : "");
                view.setLeaderId(stringObjectMap.get("tp_uid") != null ? Long.parseLong(stringObjectMap.get("tp_uid") + "") : 0l);
                view.setLeaderName(stringObjectMap.get("u_realname") != null ? (String) stringObjectMap.get("u_realname") : "");
                view.setStatus(stringObjectMap.get("ri_review_status") != null ? (Integer) stringObjectMap.get("ri_review_status") : -1);
                view.setApplyTime(stringObjectMap.get("ri_apply_time") != null ? (LocalDateTime) stringObjectMap.get("ri_apply_time") : null);
                view.setCheckTime(stringObjectMap.get("ri_check_time") != null ? (LocalDateTime) stringObjectMap.get("ri_check_time") : null);
                view.setCancelTime(stringObjectMap.get("ri_cancel_time") != null ? (LocalDateTime) stringObjectMap.get("ri_cancel_time") : null);
                viewList.add(view);
            });
            if (viewList.size() > 0) {
                PageMessage pm = new PageMessage<>(current, size);
                return pm.pageForList(viewList);
            }
        }
        return null;
    }

    /**
     * 某个队伍的所有入队申请
     *
     * @param registrationInformation
     * @return
     * @throws ParameterException
     */
    @Override
    public List<RegistrationInformation> getRegistration(RegistrationInformation registrationInformation) throws ParameterException {
        if (registrationInformation == null ||
                registrationInformation.getRiTeamId() == null ||
                registrationInformation.getRiTeamId() == 0l) {
            throw new ParameterException("获取队伍id出错");
        }
        LambdaQueryWrapper<RegistrationInformation> lqw = new LambdaQueryWrapper<RegistrationInformation>();
        if (registrationInformation.getRiTeamId() != null) {
            lqw.eq(RegistrationInformation::getRiTeamId, registrationInformation.getRiTeamId());
//            申请未审核时才进行显示
            lqw.eq(RegistrationInformation::getRiReviewStatus, 0);
        }
        return registrationInformationDao.selectList(lqw);
    }

    /**
     * 通过申请入队
     *
     * @param id
     * @param uid
     * @return
     */
    @Override
    public boolean passRegistration(Long id, Long uid) throws IOException {
        int rStatus = registrationInformationDao.selectById(id).getRiReviewStatus();
        RegistrationInformation registrationInformation = registrationInformationDao.selectById(id);
        Long teamId = registrationInformation.getRiTeamId();
        int uType = teamCompositionDao.getUserType(uid, teamId);
//        队长或者指导老师才有权限
        if (uType == 0 || uType == 1) {
            if (id != null && rStatus == 0) {
                int lackNumber = teamProfileDao.getLackNumber(teamId);
                if (lackNumber != 0) {
                    LocalDateTime localDateTime = LocalDateTime.now();
                    registrationInformation.setRiCheckTime(localDateTime);
                    registrationInformation.setRiReviewStatus(1);
                    int row = registrationInformationDao.updateById(registrationInformation);
                    TeamComposition teamComposition = new TeamComposition();
                    if (row > 0) {
                        teamProfileDao.incrementTeamMember(teamId);
                        teamComposition.setUid(registrationInformation.getRiUid());
                        teamComposition.setUrealname(registrationInformation.getRiRealname());
                        teamComposition.setTeamId(teamId);
                        teamComposition.setMemberType(2);
                        teamCompositionDao.insert(teamComposition);
                    }
                    boolean flag = row > 0;
                    if(flag){
                        webSocketServer.sendInfo("您有未读消息", registrationInformation.getRiUid());
                    }
                    return flag;
                } else {
                    throw new BusinessException(HttpStatus.CONFLICT, "队伍已满人");
                }
            } else {
                throw new BusinessException(HttpStatus.CONFLICT, "该队伍申请已经审核过");
            }
        } else {
            throw new BusinessException(HttpStatus.CONFLICT, "当前账户无权限通过入队申请");
        }

    }

    /**
     * 拒绝申请入队
     *
     * @param id
     * @param uid
     * @return
     */
    @Override
    public boolean failRegistration(Long id, Long uid) throws IOException {
        int rStatus = registrationInformationDao.selectById(id).getRiReviewStatus();
        RegistrationInformation registrationInformation = registrationInformationDao.selectById(id);
        Long teamId = registrationInformation.getRiTeamId();
        int uType = teamCompositionDao.getUserType(uid, teamId);
        if (uType == 0 || uType == 1) {
            if (id != null && rStatus == 0) {
                LocalDateTime localDateTime = LocalDateTime.now();
                registrationInformation.setRiCheckTime(localDateTime);
                registrationInformation.setRiReviewStatus(2);
                int row = registrationInformationDao.updateById(registrationInformation);
                boolean flag = row > 0;
                if (flag) {
                    webSocketServer.sendInfo("您有未读消息", registrationInformation.getRiUid());
                }
                return flag;
            } else {
                throw new BusinessException(HttpStatus.CONFLICT, "id为空或者该队伍申请已经审核过");
            }
        } else {
            throw new BusinessException(HttpStatus.CONFLICT, "当前账户无权限通过入队申请");
        }

    }

    //    提交报名信息
    @Override
    public AddRegInfoRequest addRegInf(AddRegInfoRequest addRegInfoRequest, Long uid) throws ParameterException, Exception {
        if (addRegInfoRequest == null) {
            throw new ParameterException("registrationInformation为null");
        }
        if (addRegInfoRequest.getRi_grade() <= 0 ||
                addRegInfoRequest.getRi_major().isEmpty() ||
                addRegInfoRequest.getRi_contact().isEmpty() ||
                addRegInfoRequest.getRi_intro().isEmpty() ||
                addRegInfoRequest.getRi_team_id() <= 0) {
            throw new ParameterException("registrationInformation的属性值未完全填写或者非法填写");
        }
        //当前报名用户账号存在
        if(authorityUtils.haveUser(uid) == true) {
            // 获取当前用户的基本信息(真实姓名和昵称)
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getUId, uid);
            User user = userDao.selectOne(wrapper);
            //判断当前用户是否已存在于 正在报名的队伍中
            if ((teamCompositionService.getUserInfo(addRegInfoRequest.getRi_team_id(), uid) == false)) {
                addRegInfoRequest.setRi_uid(uid);
                addRegInfoRequest.setRi_realname(user.getURealname());
                addRegInfoRequest.setRi_unickname(user.getUNickname());
                addRegInfoRequest.setRi_review_status(0);
                LocalDateTime localDateTime = LocalDateTime.now();
                addRegInfoRequest.setRi_apply_time(localDateTime);
                addRegInfoRequest.setRi_del_flag(false);//默认未删除
                Integer rows = registrationInformationDao.addRegInf(addRegInfoRequest);
                if (rows > 0) {
                    return addRegInfoRequest;
                }
            } else {
                throw new ParameterException("当前用户已存在于该队伍中");
            }
        }else {
            throw new NullPointerException("当前用户不存在");
        }
        return null;
    }

    /**
     * 修改申请信息
     *
     * @param registrationInformation
     * @param uid
     * @return
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    public String modifyRegisterInfo(RegistrationInformation registrationInformation, Long uid) throws ParameterException, Exception {
        if (registrationInformation == null || registrationInformation.getRiId() == null || registrationInformation.getRiId() < 0l) {
            throw new ParameterException("registrationInformation为空或riId为空或值非法");
        }
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空或值非法");
        }
        //检查当前申请是否有修改权限
        boolean isQualify = authorityUtils.isQualifyToModifyRegistration(registrationInformation.getRiId(), uid);
        //若记录数>0则证明该申请是该用户发起的，可修改
        if (isQualify) {
            int isSucceed = registrationInformationDao.updateById(registrationInformation);
            return isSucceed > 0 ? "修改信息成功" : "修改信息失败";
        }
        return "无该申请或用户无权修改";
    }

    /**
     * @param riId
     * @param uid
     * @return
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    public String cancelRegistration(Long riId, Long uid) throws ParameterException, Exception {
        if (riId == null || riId < 0l) {
            throw new ParameterException("riId为空或值非法");
        }
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空或值非法");
        }
        //检查当前申请是否有修改权限
        boolean isQualify = authorityUtils.isQualifyToModifyRegistration(riId, uid);
        int succeed = 0;
        if (isQualify) {
            RegistrationInformation registrationInformation = new RegistrationInformation();
            registrationInformation.setRiId(riId);
            registrationInformation.setRiCancelTime(LocalDateTime.now());
            registrationInformation.setRiReviewStatus(3);
            succeed = registrationInformationDao.updateById(registrationInformation);
        }
        return succeed > 0 ? "取消申请成功" : "取消申请失败";
    }

    /**
     * 是否有未查看的审核信息
     *
     * @param uid
     * @return null-当前数据库无此uid的账户；true-有未读审核；false-无未读审核
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    public Boolean hasNotViewedRegistrations(Long uid) throws ParameterException, Exception {
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid错误");
        }
        //确认数据库中是否有当前账户
        if (!authorityUtils.haveUser(uid)) {
            return null;
        }
        //查询未审核信息个数
        int count = registrationInformationDao.countNotViewRegistration(uid);
        return count > 0 ? true : false;
    }

    /**
     * 更改用户的申请信息都为已查看的状态
     *
     * @param uid
     * @return null-当前数据库无此uid的账户；1-修改成功；0-修改失败
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    @Transactional
    public Integer updateViewedRegistrations(Long uid) throws ParameterException, Exception {
        try {
            if (uid == null || uid < 0l) {
                throw new ParameterException("uid错误");
            }
            //确认数据库中是否有当前账户
            if (!authorityUtils.haveUser(uid)) {
                return null;
            }
            //查询未审核信息个数
            int count = registrationInformationDao.countNotViewRegistration(uid);
            //修改状态
            if (count > 0) {
                int update = registrationInformationDao.updateHadViewed(uid);
                //当有进行修改但修改行数小于未查看状态的行数时，抛错回滚
                if (update > 0 && count > update) {
                    throw new Exception("修改行数小于未查看状态的行数，非法");
                }
                //当需要进行修改（count>0）且已经修改,或无未查看的审核时，返回1
                return update > 0 ? 1 : 0;
            }
            //count==0表示无数据需修改
            return count == 0 ? 1 : 0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//回滚
            return 0;
        }
    }

}
